#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project ：idi_mes 
@File    ：output_vehicle_wip.py
@IDE     ：PyCharm 
@Date    ：9/25/24 10:25 AM 
"""
from copy import deepcopy
from typing import Dict, List, Union

from mg_app_framework import MesCode, get_organization

from common.basic_mongo import get_mongo_collection
from common.retrospect_operate.handle import filter_device_code_workorder_config
from prod_ctrl_service.tool.tool import check_cell_sn_consistent, make_retrospect_data_and_publish, get_time, \
    insert_prod_result_param, get_ng_name, send_unqualified_http, insert_unqualified_records_backup, \
    update_unqualified_records


async def check_output_vehicle_wip(params: Dict[str, Union[str, List[Dict[str, str]], List[str], int]]) \
        -> Dict[str, str]:
    """

    :param params:{
               "call_id":"JQ00386",  #接口调用方认证ID, string
               "trace_id":"8941d16b-0581-4e68-8940-a651afff4282",  #接口调用ID, string
               "upperpc_code": "UP011",    #上位机编码, string
               "user_code":"Y001",  #员工编码, string
               "equip_code":"ZP001",  # 设备编码, string
               "process_code":"2050",   # 工序编码, string, 必输
               "vehicle_no": "XEP202408001",    #托盘码, string, Y
               "cell_list": [            #托盘内电芯列表, 数组, Y
                  {
                     "cell_sn": "WW202408140001",   #电芯码, string, Y
                     "slot_no": "1"             # 通道号, string, Y
                  }
               ],
               "is_ng": 1,            # 是否NG品，int，Y，0：OK，1：NG
               "ng_code": ["E20001","E30002"],   # NG代码，数组
               "param_list": [             # 结果参数列表，数组
                  {
                     "param_code": "PM001",   # 参数编码，string，Y
                     "param_value": "0.95"    # 参数采集值，string，Y
                  }
               ]
            }
    :return:
    """
    vehicle_no = params.get("vehicle_no")
    cell_list = params.get("cell_list")
    is_ng = params.get("is_ng")
    process_code = params.get("process_code")
    equip_code = params.get("equip_code")
    cell_sn_list = [rec["cell_sn"] for rec in cell_list]
    param_list = params.get("param_list", [])
    ng_code = params.get("ng_code")
    ng_list = [{"code": ng_code, "num": 1} for ng_code in ng_code]
    # 对比托盘码在数据库中绑定的电芯码是否与入参中的电芯码一致
    if_consistent, check_result, cell_sn_list_in_db = await check_cell_sn_consistent(vehicle_no, cell_sn_list)
    if not if_consistent:
        return check_result

    error_msg = ""
    workorder_config = await filter_device_code_workorder_config(device_code=equip_code)
    bom_info = workorder_config.bom_info
    if not bom_info.product_out:
        error_msg += f"设备{equip_code}的BOM信息未配置完整;"
    # 校验是否重复出站；（如果是不良品返工，需要先给不良品打上返工标记，并限制返工次数）
    # qr_code_has_used = await check_repeat_in_or_out(
    #     procedure_code=process_code, qr_code_list=cell_sn_list_in_db, op_type=RetrospectType.PRODUCT_OUT
    # )
    # if qr_code_has_used:
    #     error_msg += f"条码在工序{process_code}上已经有出站记录"
    if error_msg:
        result = {
            "code": MesCode.fail,  # 接口应答状态代码, success：成功; fail：失败, string
            "data": {},  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
            "info": error_msg,
        }
        return result
    # 根据入参构建的需要写入到出站参数表的数据
    prod_result_param_list = []
    # 根据入参构建的需要写入到不合格品记录表的数据
    unqualified_records: list = []
    # 根据入参构建的需要写入到不合格品记录表的数据的备份
    unqualified_records_backup: list = []
    # 存放每一个入参的电芯码对应的投料原材料批次码，最终要在出站完成后对这些原材料批次码关联的符合查询条件的不合格品记录进行更新操作
    input_wip_list: list = []
    # 追溯关系建立
    for cell_sn in cell_sn_list_in_db:
        param = {
            "procedure_code": process_code,
            "device_code": equip_code,
            "is_ng": is_ng,
            "qr_code": cell_sn,
            "ng_list": ng_list,
            "material_code": None
        }
        # retros_result: 构建追溯是否成功; retros_msg: 成功或者报错信息;
        # input_lot_no_list: 电芯码关联的投料批次码，仅当追溯数据构建未报错时为非空列表
        retros_result, retros_msg, input_lot_no_list = await make_retrospect_data_and_publish(param=param)
        if not retros_result:
            error_msg += retros_msg
        input_wip_list.extend(input_lot_no_list)
        # 构建出站参数表数据
        prod_result_param_list.append({
            "call_id": params.get("call_id"),  # 接口调用方认证ID
            "trace_id": params.get("trace_id"),  # 接口调用ID
            "upperpc_code": params.get("upperpc_code"),  # 上位机编码
            "user_code": params.get("user_code"),  # 员工编码
            "equip_code": params.get("equip_code"),  # 设备编码
            "process_code": params.get("process_code"),  # 工序编码
            "wip_no": cell_sn,
            "param_list": param_list,
            "time": get_time(),
            "data_source": "037"  # 此字段用于标记由哪个接口构建的数据
        })
        if is_ng == 1:
            # 同一个码值的不合格品记录数目取决于有多少个ng-code
            for ng_item in ng_list:
                unqualified_reason_name = await get_ng_name(ng_item['code'])
                unqualified_data = {
                    "qr_code": cell_sn,  # 码值
                    "product_code": bom_info.product_out[0].material_code,  # 不合格品物料编码
                    "product_name": bom_info.product_out[0].material_name,  # 不合格品物料名称
                    "process_code": workorder_config.procedure_code,  # 生产工序编码
                    "process_name": workorder_config.procedure_name,  # 生产工序名称
                    "device_code": workorder_config.device_code,  # 对应生产设备编码
                    "device_name": workorder_config.device_name,  # 对应生产设备编码
                    "production_date": get_time()[:10],  # 出库日期，格式为 %Y-%m-%d
                    "unqualified_reason_code": ng_item['code'],  # 不合格原因编码（对应不合格品基础配置中的不良品编码）
                    "unqualified_reason_name": unqualified_reason_name,  # 不合格原因（对应不合格品基础配置中的不良品名称）
                    "ok_qty": None,  # 合格数
                    "ng_qty": None,  # 不合格数
                    'user_name': params.get('user_code', '')
                }
                unqualified_records.append(unqualified_data)
                unqualified_data_backup = deepcopy(unqualified_data)
                unqualified_data_backup.update({"source": '037'})
                unqualified_records_backup.append(unqualified_data_backup)

    if error_msg:
        result = {
            "code": MesCode.fail,  # 接口应答状态代码, success：成功; fail：失败, string
            "data": {},  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
            "info": error_msg,
        }
        return result
    # 写入出站参数
    if prod_result_param_list:
        await insert_prod_result_param(params=prod_result_param_list)
    # 将不合格品记录发送至不合格品app
    if unqualified_records:
        await send_unqualified_http(unqualified_records)
    # 本地将不合格品记录备份写入备份表
    if unqualified_records_backup:
        await insert_unqualified_records_backup(unqualified_records_backup)
    # 在进站后更新不合格品记录信息
    await update_unqualified_records(input_wip_list, process_code)
    data = {
        "call_id": params.get("call_id"),  # 接口调用方认证ID, string
        "trace_id": params.get("trace_id"),  # 接口调用ID, string
        "upperpc_code": params.get("upperpc_code"),  # 上位机编码, string
        "user_code": params.get("user_code"),  # 员工编码, string
        "equip_code": params.get("equip_code"),  # 设备编码, string
        "process_code": params.get("process_code"),  # 工序编码, string
        "vehicle_no": params.get("vehicle_no"),  # 托盘码, string, Y
        "cell_list": params.get("cell_list"),
        "is_ng": params.get("is_ng"),  # 是否NG品，int，Y，0：OK，1：NG
        "ng_code": params.get("ng_code"),  # NG代码，数组
        "param_list": params.get("param_list"),
        "time": get_time()
    }
    await insert_data(data=data)
    result = {
        "code": MesCode.success,  # 接口应答状态代码, success：成功; fail：失败, string
        "data": {},  # 接口返回结果描述, json数组, 本接口不需要返回数据，返回null
        "info": "OK",  # 接口返回信息描述, 如果为fail, 则为fail的异常描述信息, string
    }
    return result


async def insert_data(data):
    """
    :param data:
    :return:
    """
    collection = get_mongo_collection(
        database_name=f"{get_organization()}_mes",
        collection_name=f"output_vehicle_wip_record",
    )
    await collection.insert_one(data)
